package com.zatom.newscore.crawler;

import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.zatom.newscore.common.BaseResponse;
import com.zatom.newscore.common.FreezeAndFilterHandler;
import com.zatom.newscore.utils.U;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openjdk.nashorn.api.scripting.ScriptObjectMirror;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping({"/nowscore"})
@Api(value = "获取NowScore数据", tags = {"page"})
public class NowScore {
  private static final Logger log = LogManager.getLogger(com.zatom.newscore.crawler.NowScore.class);

  @Value("${url.page:http://live.nowscore.com/2in1.aspx}")
  private String pageUrl;

  @Value("${url.data:http://live.nowscore.com/data/sbOddsData.js}")
  private String dataUrl;

  @Value("${url.match:http://live.nowscore.com/data/bf.js}")
  private String matchUrl;

  @Autowired
  private RestTemplate rest;

  public ScriptObjectMirror getOddData() {
    String odd = (String)this.rest.getForObject(this.dataUrl + "?" + this.dataUrl + "000", String.class, new Object[0]);
    log.debug(odd);
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("js");
    odd = "var sData={};" + odd + " sData;";
    ScriptObjectMirror obj = null;
    try {
      obj = (ScriptObjectMirror)engine.eval(odd);
    } catch (ScriptException e) {
      e.printStackTrace();
    }
    log.debug(U.json(obj));
    return obj;
  }

  public ScriptObjectMirror getMatchData() {
    String match = (String)this.rest.getForObject(this.matchUrl + "?" + this.matchUrl + "000", String.class, new Object[0]);
    log.debug(match);
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("js");
    match = "ShowBf=function(){return A;};" + match;
    ScriptObjectMirror obj = null;
    try {
      obj = (ScriptObjectMirror)engine.eval(match);
    } catch (ScriptException e) {
      e.printStackTrace();
    }
    log.debug(U.json(obj));
    return obj;
  }

  private List<ScoreXLS> processData() {
    List<ScoreXLS> list = new ArrayList<>();
    ScriptObjectMirror matchData = getMatchData();//赛事数据
    ScriptObjectMirror oddData = getOddData();//赛事详情
    ScriptObjectMirror v = null;
    ScoreXLS s1 = null;//第一行
    ScoreXLS s2 = null;//第二行
    for (Object obj : matchData.values()) {
      v = (ScriptObjectMirror)obj;
      String id = v.get("0").toString();
      ScriptObjectMirror ood = (ScriptObjectMirror)oddData.get(id);
      if (ood == null) {
        log.debug("" + v.get("4") + "|odd_null");
        continue;
      }
      log.debug("" + v.get("4") + "|" + v.get("4"));
      s1 = (new ScoreXLS()).setName(v.get("4").toString()).setTime(v.get("10").toString()).setBegin(getField(ood, "3", "0")).setCurrent(getField(ood, "3", "3")).setBeginGive(getField(ood, "3", "1")).setCurrentGive(getField(ood, "3", "4")).setBeginSize(getField(ood, "4", "1")).setBeginSizeData(getField(ood, "4", "0")).setCurrentSize(getField(ood, "4", "4")).setCurrentSizeData(getField(ood, "4", "3"))
              .setHalfHome(getField(ood, "5", "0")).setHalfDraw(getField(ood, "5", "1")).setHalfGuest(getField(ood, "5", "2"))
              .setResult(getHalfMatchResult(v)).setAllBegin(getField(ood, "0", "0")).setAllCurrent(getField(ood, "0", "3")).setAllBeginGive(getField(ood, "0", "1")).setAllCurrentGive(getField(ood, "0", "4")).setAllBeginSize(getField(ood, "2", "1")).setAllBeginSizeData(getField(ood, "2", "0")).setAllCurrentSize(getField(ood, "2", "4")).setAllCurrentSizeData(getField(ood, "2", "3"))
              .setAllHome(getField(ood, "1", "0")).setAllDraw(getField(ood, "1", "1")).setAllGuest(getField(ood, "1", "2"))
              .setAllResult(getAllMatchResult(v));
      s2 = (new ScoreXLS()).setBegin(getField(ood, "3", "2")).setCurrent(getField(ood, "3", "5")).setBeginSizeData(getField(ood, "4", "2")).setCurrentSizeData(getField(ood, "4", "5"))
              .setHalfHome(getField(ood, "5", "3")).setHalfDraw(getField(ood, "5", "4")).setHalfGuest(getField(ood, "5", "5"))
              .setAllBegin(getField(ood, "0", "2")).setAllCurrent(getField(ood, "0", "5")).setAllBeginSizeData(getField(ood, "2", "2")).setAllCurrentSizeData(getField(ood, "2", "5"))
              .setAllHome(getField(ood, "1", "3")).setAllDraw(getField(ood, "1", "4")).setAllGuest(getField(ood, "1", "5"))
      ;
      list.add(s1);
      list.add(s2);
    }
    log.info(U.json(list));
    return list;
  }

  private String getField(ScriptObjectMirror v, String k1, String k2) {
    Object v1 = v.get(k1);
    if (v1 == null)
      return null;
    Object v2 = ((ScriptObjectMirror)v.get(k1)).get(k2);
    if (v2 == null)
      return null;
    return v2.toString();
  }

  public String getHalfMatchResult(ScriptObjectMirror v) {
    if (v == null || !v.containsKey("15") || !v.containsKey("16"))
      return null;
    return "" + v.get("15") + "-" + v.get("16");
  }

  public String getAllMatchResult(ScriptObjectMirror v) {
    Integer state = (Integer)v.get("12");
    if (v == null || !v.containsKey("13") || !v.containsKey("14"))
      return null;
    if (state.intValue() != -1 && state.intValue() <= 0)
      return null;
    return "" + v.get("13") + "-" + v.get("14");
  }

  @GetMapping({"/data"})
  @ApiOperation("获取页面最新数据")
  public BaseResponse<String> getNewData() {
    List<ScoreXLS> lsScoreXLS = processData();
    return BaseResponse.success(U.json(lsScoreXLS));
  }

  @GetMapping({"/download"})
  @ApiOperation("获取页面最新数据Excel")
  public void download(HttpServletResponse response) throws IOException {
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setCharacterEncoding("utf-8");
    String dateStr = DateUtil.formatDateTime(new Date());
    String fileName = URLEncoder.encode("NewScore-" + dateStr, "UTF-8").replaceAll("\\+", "%20");
    response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    ((ExcelWriterBuilder)EasyExcel.write((OutputStream)response.getOutputStream(), ScoreXLS.class)
      .registerWriteHandler((WriteHandler)new LongestMatchColumnWidthStyleStrategy())).registerWriteHandler(new FreezeAndFilterHandler())
      .sheet("导出").doWrite(processData());
  }
}
